package fcl.platform;

import java.io.File;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.hardware.Sensor;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

public class DataLoggerController extends Activity {
	private TextView accel_fields[] = new TextView[3];
//s	private TextView magnet_fields[] = new TextView[3];
	private ToggleButton button[] = new ToggleButton[8];
	private ToggleButton servicebutton;
	
	private IRemoteService mService = null;
	
	private  boolean isInternalButtonEvent = false;
	
	private static final int SENSOR_UPDATE = 1;
	
    private Handler mHandler = new Handler() {
        @Override public void handleMessage(Message msg) {
            switch (msg.what) {
                case SENSOR_UPDATE:
                	DataLoggerController.this.updateSensorData(msg.arg1, msg.getData().getFloatArray("DATA"));
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };
    
    private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
        /**
         * This is called by the remote service regularly to tell us about
         * new values.  Note that IPC calls are dispatched through a thread
         * pool running in each process, so the code executing here will
         * NOT be running in our main thread like most other things -- so,
         * to update the UI, we need to use a Handler to hop over there.
         */
		public void valueChanged(int sensor_type, float[] data)
				throws RemoteException {
			Message msg = mHandler.obtainMessage(SENSOR_UPDATE, sensor_type, 0);
			Bundle b = new Bundle();
			b.putFloatArray("DATA", data);
			msg.setData(b);
			mHandler.sendMessage(msg);
		}
    };
	
    private ServiceConnection mConnection = new ServiceConnection() {
    	public void onServiceConnected(ComponentName className, IBinder service) {
    		mService = IRemoteService.Stub.asInterface(service);
    		try {
    			mService.registerCallback(mCallback);
    			DataLoggerController.this.enableButtons();
    		} catch (RemoteException e) {
    			mService = null;
    		}
        }
        public void onServiceDisconnected(ComponentName className) {
            mService = null;
            DataLoggerController.this.disableButtons();
        }
    };

    private void enableButtons() {
    	isInternalButtonEvent = true;
    	servicebutton.setChecked(true);
    	for(ToggleButton b : button) {
    		b.setEnabled(true);
    	}
    	Mode cur;
		try {
			cur = Mode.toMode(mService.getMode());
		   	if(cur != Mode.IDLE)
	    		button[cur.mode -1].setChecked(true);
		} catch (RemoteException e) {
			Toast.makeText(getApplicationContext(), "Error to connect to service.", Toast.LENGTH_SHORT).show();
			unbindService();
		}
		isInternalButtonEvent = false;
    }
    
	private void disableButtons() {
    	isInternalButtonEvent = true;
    	servicebutton.setChecked(false);
    	for(ToggleButton b : button) {
    		b.setChecked(false);
    		b.setEnabled(false);
    	}
    	isInternalButtonEvent = false;
    }
    private void updateSensorData(int type, float[] data) {
    	if(type == Sensor.TYPE_ACCELEROMETER) {
    		accel_fields[0].setText(Float.toString(data[0]));
    		accel_fields[1].setText(Float.toString(data[1]));
    		accel_fields[2].setText(Float.toString(data[2]));
    	}

    }
	private boolean isMyServiceRunning() {
		return DataLogger.is_service_active(this);
	}
	private void activeMode(Mode m)	{
		isInternalButtonEvent = true;
		if(mService != null) {
			try {
				Mode cur = Mode.toMode(mService.getMode());
				if(cur != m) {
					mService.setMode(m.mode);
					if(cur != Mode.IDLE)
						button[cur.mode -1].setChecked(false);
				}
			} catch (RemoteException e) {
				Toast.makeText(getApplicationContext(), "Error to connect to service.", Toast.LENGTH_SHORT).show();
				unbindService();
			}
		}
		isInternalButtonEvent = false;
	}
	private void deactiveMode(Mode m)
	{
		isInternalButtonEvent = true;
		if(mService != null) {
			try {
				Mode cur = Mode.toMode(mService.getMode());
				if(cur != m && cur != Mode.IDLE) {
					button[cur.mode -1 ].setChecked(true);
				}
				else {
					mService.setMode(Mode.IDLE.mode);
				}
			} catch (RemoteException e) {
				Toast.makeText(getApplicationContext(), "Error to connect to service.", Toast.LENGTH_SHORT).show();
				unbindService();
			}
		}
		isInternalButtonEvent = false;
	}
	class ModeChangeListener implements ToggleButton.OnCheckedChangeListener {
		private final Mode m;
		public ModeChangeListener(Mode m) {
			this.m = m;
		}
		public void onCheckedChanged(CompoundButton arg0, boolean checked) {
			if(isInternalButtonEvent == false)
			{
				if(checked)
					DataLoggerController.this.activeMode(m);
				else
					DataLoggerController.this.deactiveMode(m);
			}
		}
    }
    
	private void enableService() {
		if(!DataLogger.start_service(this) || !bindService()) {
			disableButtons();
			Toast.makeText(getApplicationContext(), getString(R.string.data_logger_failed), Toast.LENGTH_SHORT).show();
		}
	}
	private void disableService() {
		unbindService();
		DataLogger.stop_service(this);
	}
	private boolean bindService() {
        return bindService(new Intent(getString(R.string.remote_service)), mConnection, 0);
	}
	private void unbindService() {
		if(mService != null) {
			try {
				mService.unregisterCallback(mCallback);
			} catch (RemoteException e) {
			}
			unbindService(mConnection);
			mService = null;
		}
		disableButtons();
	}
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        servicebutton = (ToggleButton) findViewById(R.id.ServiceButton);
        button[0] = (ToggleButton) findViewById(R.id.button1);
        button[1] = (ToggleButton) findViewById(R.id.button2);
        button[2] = (ToggleButton) findViewById(R.id.button3);
        button[3] = (ToggleButton) findViewById(R.id.button4);
        button[4] = (ToggleButton) findViewById(R.id.button5);
        button[5] = (ToggleButton) findViewById(R.id.button6);
        button[6] = (ToggleButton) findViewById(R.id.button7);
        button[7] = (ToggleButton) findViewById(R.id.button8);
    	accel_fields[0] = (TextView) findViewById(R.id.accel_x);
    	accel_fields[1] = (TextView) findViewById(R.id.accel_y);
    	accel_fields[2] = (TextView) findViewById(R.id.accel_z);

                
       	servicebutton.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
    		public void onCheckedChanged(CompoundButton arg0, boolean checked) {
    			if(isInternalButtonEvent == false)
    			{
    				if(checked)
    					enableService();
    				else
    					disableService();
    			}
    		}
    	});
        button[0].setOnCheckedChangeListener(new ModeChangeListener(Mode.toMode(1)));
        button[1].setOnCheckedChangeListener(new ModeChangeListener(Mode.toMode(2)));
        button[2].setOnCheckedChangeListener(new ModeChangeListener(Mode.toMode(3)));
        button[3].setOnCheckedChangeListener(new ModeChangeListener(Mode.toMode(4)));
        button[4].setOnCheckedChangeListener(new ModeChangeListener(Mode.toMode(5)));
        button[5].setOnCheckedChangeListener(new ModeChangeListener(Mode.toMode(6)));
        button[6].setOnCheckedChangeListener(new ModeChangeListener(Mode.toMode(7)));
        button[7].setOnCheckedChangeListener(new ModeChangeListener(Mode.toMode(8)));
    }
    @Override
    public void onResume() {
    	super.onResume();

        if(!isMyServiceRunning() || !bindService())
        {
        	disableService();
        }
    }
    @Override
    public void onPause() {
    	super.onPause();
    	unbindService();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.logger_menu, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
        case R.id.upload:
        	doUpload();
        	return true;        
        case R.id.exit:
        	finish();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }
    
	private void doUpload() {
		String upload_file_name = getString(R.string.upload_file);
		String folder_name = getString(R.string.data_folder);
		final File upload_file = new File(Environment.getExternalStorageDirectory()
				+ folder_name + upload_file_name);
		if(upload_file.exists() && upload_file.length() ==0)
		{
			upload_file.delete();
		}
		if (!upload_file.exists()) {
			if(mService != null) {
				try {
					mService.rollover_data_file(upload_file_name);
				} catch (RemoteException e) {}
			} else {
				final File data_file = new File(Environment.getExternalStorageDirectory()
						+ folder_name + getString(R.string.data_file));
				if(data_file.exists()) {
					data_file.renameTo(upload_file);
				}
			}
		}
		if(upload_file.exists() && upload_file.length() > 0) {
			startService(new Intent(getString(R.string.upload_service)));
		}
	}
}